//============================================================================================
/**
 * @file	d_saito_st.c
 * @brief	デバッグ常駐部分
 * @author	Nozomu Saito
 */
//============================================================================================
#ifdef PM_DEBUG

#include "d_saito_st.h"
#include "system/brightness.h"
#include "system/wipe.h"
#include "field/fieldsys.h"
#include "system/snd_tool.h"
#include "system/snd_play.h"

#include "field/field_subproc.h"
#include "application/pokethlon_frame.h"
#include "application/museum.h"
#include "demo/linear/linear_demo_call.h"
#include "demo/ship/ship_demo_call.h"

typedef enum{
	DBG_SAI_FADEOUT = 0,
	DBG_SAI_FADEOUT_WAIT,
	DBG_SAI_DEBUG_PROC,
	DBG_SAI_FADEIN,
	DBG_SAI_FADEIN_WAIT,
//	DBG_SAI_FLD_PROC,
};

typedef struct DEBUG_SAITO_ST_WORK_tag
{
	USER_FUNC UserFunc;
	int Seq;
	FIELDSYS_WORK * fsys;
	void *Work;			//汎用ワーク
	int BGM;
}DEBUG_SAITO_ST_WORK;

typedef struct D_LINEAR_EV_WORK_tag
{
	int Dir;
}D_LINEAR_EV_WORK;

typedef struct D_SHIP_EV_WORK_tag
{
	int Dir;
}D_SHIP_EV_WORK;

DEBUG_PKTHLN_WORK DebugPkthlnWk = {
	FALSE,
	{0,0,0,0,0},
	0,
	{
		{0,0,0,0,0},
		{0,0,0,0,0},
		{0,0,0,0,0},
	},
	FALSE,
};

int DebugLegFldDemoFlg = 0;

extern void PokeSelectCall_SetupEvent(FIELDSYS_WORK *fsys);

static BOOL GMEVENT_DebugPokeSelStart(GMEVENT_CONTROL * event);
static BOOL GMEVENT_DebugLinearStart(GMEVENT_CONTROL * event);
static BOOL GMEVENT_DebugShipStart(GMEVENT_CONTROL * event);

PAIR_POKE_DBG PairPokeDbg = {
	0,0,0
};

//--------------------------------------------------------------------------------------------
/**
 * メモリアロケーション関数
 *
 * @param	fsys			フィールドシステムポインタ
 * @param	inHeapID		ヒープＩＤ
 *
 * @return	work			メモリポインタ
 */
//--------------------------------------------------------------------------------------------
DBG_SAI_ST_PTR DebugSaitoSt_AllocWork(FIELDSYS_WORK *fsys, const int inHeapID)
{
	DBG_SAI_ST_PTR work = sys_AllocMemory(inHeapID,sizeof(DEBUG_SAITO_ST_WORK));
	work->Seq = 0;
	work->fsys = fsys;
	work->Work = NULL;
	work->BGM = BGM_NONE;
	return work;
}

//--------------------------------------------------------------------------------------------
/**
 * メモリ解放
 *
 * @param	inHeapID		ヒープＩＤ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void DebugSaitoSt_FreeWork(DBG_SAI_ST_PTR st_ptr)
{
	if ( st_ptr->Work != NULL ){
		sys_FreeMemoryEz(st_ptr->Work);
	}
	sys_FreeMemoryEz(st_ptr);
}

//--------------------------------------------------------------------------------------------
/**
 * 関数設定関数
 *
 * @param	st_ptr			常駐デバッグデータポインタ
 * @param	func			関数ポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void DebugSaitoSt_SetFunc(DBG_SAI_ST_PTR st_ptr, USER_FUNC func)
{
	st_ptr->UserFunc = func;
}

//--------------------------------------------------------------------------------------------
/**
 * ワークセット関数
 *
 * @param	st_ptr			常駐デバッグデータポインタ
 * @param	work			ワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void DebugSaitoSt_SetWork(DBG_SAI_ST_PTR st_ptr, void *work)
{
	st_ptr->Work = work;
}

//--------------------------------------------------------------------------------------------
/**
 * ワーク取得関数
 *
 * @param	st_ptr			常駐デバッグデータポインタ
 *
 * @return	work	ワーク
 */
//--------------------------------------------------------------------------------------------
void *DebugSaitoSt_GetWork(DBG_SAI_ST_PTR st_ptr)
{
	return st_ptr->Work;
}


//--------------------------------------------------------------------------------------------
/**
 * 関数設定関数
 *
 * @param	st_ptr			常駐デバッグデータポインタ
 * @param	func			関数ポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
FIELDSYS_WORK * DebugSaitoSt_GetFieldSysPtr(DBG_SAI_ST_PTR st_ptr)
{
	return st_ptr->fsys;
}

//--------------------------------------------------------------------------------------------
/**
 * 関数制御タスク
 *
 * @param	tcb
 * @param	work			ワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void DebugSaitoSt_FuncCall(TCB_PTR tcb, void* work)
{
	DBG_SAI_ST_PTR d_work = (DEBUG_SAITO_ST_WORK*)work;

	switch(d_work->Seq){
	case DBG_SAI_FADEOUT:
		WIPE_SYS_Start(WIPE_PATTERN_WMS,
				WIPE_TYPE_FADEOUT,
				WIPE_TYPE_FADEOUT,0x0000,COMM_BRIGHTNESS_SYNC,1,HEAPID_BASE_DEBUG
				);
		d_work->Seq = DBG_SAI_FADEOUT_WAIT;
		break;
	case DBG_SAI_FADEOUT_WAIT:
		if(!WIPE_SYS_EndCheck()){
			break;
		}
		//画面解放


		//ファンクション実行、プロセス登録
		{
///			void (*dproc_call)(void*);
///			dproc_call = d_work->UserFunc;
			d_work->UserFunc(d_work);
			FieldSystemProc_SeqHoldEnd();
		}
		d_work->Seq = DBG_SAI_DEBUG_PROC;
		break;
	case DBG_SAI_DEBUG_PROC:
//プロセス終了待ち
		if(FieldEvent_Cmd_WaitSubProcEnd(d_work->fsys)){
			break;
		}
		d_work->Seq = DBG_SAI_FADEIN;
		//フィールドマッププロセス復帰
		FieldEvent_Cmd_SetMapProc(d_work->fsys);
		break;
	case DBG_SAI_FADEIN:
		//フィールドプロセス開始終了待ち
		if(FieldEvent_Cmd_WaitMapProcStart(d_work->fsys)){
			//デバッグメニュー復帰
///			DebugMiyukiViewInit(wp,wp->fsys,wp->List,wp->Cursor);
			//ブラックインリクエスト
			WIPE_SYS_Start(WIPE_PATTERN_WMS,
				WIPE_TYPE_FADEIN,
				WIPE_TYPE_FADEIN,0x0000,COMM_BRIGHTNESS_SYNC,1,HEAPID_BASE_DEBUG
				);
			d_work->Seq = DBG_SAI_FADEIN_WAIT;
			//BGMが保存されていれば復帰
			if(d_work->BGM != BGM_NONE){
				Snd_BgmPlay(d_work->BGM);
			}
			break;
		}
		break;
	case DBG_SAI_FADEIN_WAIT:
		if(!WIPE_SYS_EndCheck()){
			break;
		}
		//フィールド復帰
		OS_Printf("フィールドに復帰\n");

		MORI_PRINT( "heapid_world is %d\n",sys_CheckHeapSafe( HEAPID_WORLD ));

		DebugSaitoSt_FreeWork(d_work);
		TCB_Delete(tcb);

///		FieldSystemProc_SeqHold();
///		TCB_ChangeFunc(tcb, NULL/*DebugMiyukiMain*/);
		break;
	}
}

//--------------------------------------------------------------------------------------------
/**
 * BGMナンバー保存
 *
 * @param	DBG_SAI_ST_PTR st_ptr
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void SaveBGMNo(DBG_SAI_ST_PTR st_ptr)
{
	st_ptr->BGM = Snd_NowBgmNoGet();
}


typedef struct D_POKE_SEL_EV_WORK_tag
{
	int Seq;
}D_POKE_SEL_EV_WORK;

//--------------------------------------------------------------------------------------------
/**
 * 3体選択イベントセット
 *
 * @param	fsys		フィールドシステムポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void DebugSetPokeSelEvent(FIELDSYS_WORK * fsys)
{
	D_POKE_SEL_EV_WORK *work = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(D_POKE_SEL_EV_WORK));

	work->Seq = 0;

	//イベントを作成
	FieldEvent_Set(fsys, GMEVENT_DebugPokeSelStart, work);
}

//--------------------------------------------------------------------------------------------
/**
 * 3体選択イベント
 *
 * @param	event		イベントポインタ
 *
 * @return	BOOL		TRUE:終了　FALSE:継続
 */
//--------------------------------------------------------------------------------------------
static BOOL GMEVENT_DebugPokeSelStart(GMEVENT_CONTROL * event)
{
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	D_POKE_SEL_EV_WORK *work = FieldEvent_GetSpecialWork(event);

	switch (work->Seq) {
	case 0:
		PokeSelectCall_SetupEvent(fsys);
		work->Seq++;
		break;
	case 1:
		sys_FreeMemoryEz(work);
		return TRUE;
	}
	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * リニアイベントセット
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	inDir		方向
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void DebugSetLinearEvent(FIELDSYS_WORK * fsys, const int inDir)
{
	D_LINEAR_EV_WORK *work = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(D_LINEAR_EV_WORK));

	work->Dir = inDir;

	//イベントを作成
	FieldEvent_Set(fsys, GMEVENT_DebugLinearStart, work);
}

//--------------------------------------------------------------------------------------------
/**
 * リニアイベント
 *
 * @param	event		イベントポインタ
 *
 * @return	BOOL		TRUE:終了　FALSE:継続
 */
//--------------------------------------------------------------------------------------------
static BOOL GMEVENT_DebugLinearStart(GMEVENT_CONTROL * event)
{
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	int *seq = FieldEvent_GetSeqWork(event);
	D_LINEAR_EV_WORK *work = FieldEvent_GetSpecialWork(event);

	switch (*seq) {
	case 0:
		{
			int zone;
			u8 dir;
			int x,z;

			//現在ゾーンID取得
			zone = fsys->location->zone_id;
			//自機の向き取得
			dir = Player_DirGet( fsys->player );
			//自機座標取得
			x = Player_NowGPosXGet( fsys->player );
			z = Player_NowGPosZGet( fsys->player );

			LinearDemo_CallDemo(fsys, work->Dir, dir, zone, x, z);
		}
		(*seq)++;
		break;
	case 1:
		sys_FreeMemoryEz(work);
		return TRUE;
	}
	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * 船イベントセット
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	inDir		方向
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void DebugSetShipEvent(FIELDSYS_WORK * fsys, const int inDir)
{
	D_SHIP_EV_WORK *work = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(D_SHIP_EV_WORK));

	work->Dir = inDir;

	//イベントを作成
	FieldEvent_Set(fsys, GMEVENT_DebugShipStart, work);
}

//--------------------------------------------------------------------------------------------
/**
 * 船イベント
 *
 * @param	event		イベントポインタ
 *
 * @return	BOOL		TRUE:終了　FALSE:継続
 */
//--------------------------------------------------------------------------------------------
static BOOL GMEVENT_DebugShipStart(GMEVENT_CONTROL * event)
{
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	int *seq = FieldEvent_GetSeqWork(event);
	D_SHIP_EV_WORK *work = FieldEvent_GetSpecialWork(event);

	switch (*seq) {
	case 0:
		{
			int zone;
			u8 dir;
			int x,z;

			//現在ゾーンID取得
			zone = fsys->location->zone_id;
			//自機の向き取得
			dir = Player_DirGet( fsys->player );
			//自機座標取得
			x = Player_NowGPosXGet( fsys->player );
			z = Player_NowGPosZGet( fsys->player );

			ShipDemo_CallDemo(fsys, work->Dir, dir, zone, x, z);
		}
		(*seq)++;
		break;
	case 1:
		sys_FreeMemoryEz(work);
		return TRUE;
	}
	return FALSE;
}

#if 0
//==============================================================================
/**
 * @brief   ポケスロンレコード画面を呼び出す
 *
 * @param   work	DBG_SAI_ST_PTRのvoidポインタ
 *
 * @retval  none
 */
//==============================================================================
void DebugSetPokethlonRecordEvent( void *work )
{
	DBG_SAI_ST_PTR d_work = (DEBUG_SAITO_ST_WORK*)work;
	void *wk;

	wk = FieldPokethlonRecord_SetProc( d_work->fsys );

	DebugSaitoSt_SetWork( d_work, wk );


}
#endif

#endif	//PM_DEBUG